package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
//import com.itextpdf.text.Document;
//import com.itextpdf.text.pdf.PdfCopy;
//import com.itextpdf.text.pdf.PdfImportedPage;
//import com.itextpdf.text.pdf.PdfReader;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.system.domain.DrawGraphInfo;
import com.ruoyi.system.domain.DrawGraphObj;
import com.ruoyi.system.domain.DrawImgFrame;
import com.ruoyi.system.domain.SvgFontElementModel;
import com.ruoyi.system.service.GraphPDFService;
import com.ruoyi.system.service.IDrawGraphInfoService;
import com.ruoyi.system.service.IDrawGraphObjService;
import com.ruoyi.system.service.IDrawImgFrameService;
import com.ruoyi.system.utils.SvgFontUtil;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.graphics.PdfLayoutType;
import com.spire.pdf.graphics.PdfMargins;
import com.spire.pdf.graphics.PdfTemplate;
import com.spire.pdf.graphics.PdfTextLayout;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.geom.Point2D;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GraphPDFServiceImpl implements GraphPDFService {
    @Resource
    private ResourceLoader resourceLoader;

    @Resource
    private IDrawGraphInfoService drawGraphInfoService; //图纸

    @Resource
    private IDrawImgFrameService drawImgFrameService; //图框

    @Resource
    private IDrawGraphObjService drawGraphObjService; //图形

    private List<String> lines = new ArrayList<>();

    @PostConstruct
    public void initReadSvgTemplate() {
        try {
            InputStream inputStream = resourceLoader.getResource("classpath:PDF/graphInfo.svg").getInputStream();
            this.lines = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getGraphSvgXml(String graphId,int flag) {
        String result;
        //获取图纸信息
        DrawGraphInfo graphInfo = drawGraphInfoService.getById(graphId);
        if (graphInfo== null) {
            throw new SecurityException("图纸信息不存在！");
        }

        //1.组装图框svg
        DrawImgFrame drawImgFrame = drawImgFrameService.getById(graphInfo.getImgFrameId());
        //图框去除<?xml version="1.0" encoding="UTF-8" standalone="no"?>
        String xmlTitle = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
        String svgContent = drawImgFrame.getSvgContent();
        String imgframe_svg_content = svgContent.replace(xmlTitle, "");

        //2.组装图形svg
        List<DrawGraphObj> objList = drawGraphObjService.list(new LambdaQueryWrapper<DrawGraphObj>()
                .eq(DrawGraphObj::getGraphId, graphId)
                .ne(DrawGraphObj::getDrawingMethod, "PIPELINE")
                .orderByAsc(DrawGraphObj::getCreatedIndex));
        StringBuffer graph_obj_svg_geometry = new StringBuffer();
        if (CollectionUtils.isNotEmpty(objList)) {
            String obj_str;
            String objMatrix;
            String svgXml;
            for (DrawGraphObj drawGraphObj : objList) {
                objMatrix = "<g id=\"obj_instance_id\" pointer-events=\"bounding-box\" transform=\"matrix(obj_matrix)\">";
                obj_str = objMatrix.replaceAll("obj_instance_id", drawGraphObj.getInstanceId())
                        .replaceAll("obj_matrix", drawGraphObj.getMatrix());
                // 特殊文字处理
                svgXml = getFontSvg(drawGraphObj.getSvgGeometry(),flag);
                graph_obj_svg_geometry.append(obj_str).append(svgXml).append("</g>");
            }
        }

        //3.替换文本
        List<String> processedLines = lines.stream().map(line -> line
                        .replaceAll("img_frame_id", graphInfo.getImgFrameId())
                        .replaceAll("imgframe_svg_content", imgframe_svg_content)
                        .replaceAll("graph_obj_svg_geometry", graph_obj_svg_geometry.toString()))
                .collect(Collectors.toList());

        //4.数据格式化
        result = String.join("\n", processedLines);
        log.info(graphId + "图纸数据生成成功！");
        return result;
    }

    @Override
    public void exportGraph2PDF(HttpServletResponse response, String graphIds) {
        List<String> pdfFiles = new ArrayList<>();
        String[] graphIdArray = graphIds.split(",");
        String svgStr;
        // 本地资源路径 cloudDream/uploadPath/svg
        String filePath = RuoYiConfig.getProfile() + "/svg";
        List<String> files = new ArrayList<>();
        List<String> tempFilePaths = new ArrayList<>();
        for (String graphId : graphIdArray) {
            //获取图纸信息
            DrawGraphInfo graphInfo = drawGraphInfoService.getById(graphId);
            String fileName = graphInfo.getGraphName() + ".svg";
            svgStr = getGraphSvgXml(graphId,1);
            // 更新svg临时文件
            uploadSvg(svgStr,filePath,fileName);

            PdfDocument newPdf = new PdfDocument();
            PdfDocument originPdf = new PdfDocument();
            originPdf.loadFromSvg(filePath + "/" + fileName);
            for (int i = 0; i < originPdf.getPages().getCount(); i++) {
                // 设置页面大小
                PdfPageBase newPage = newPdf.getPages().add(new Dimension(graphInfo.getGraphWidth().intValue(), graphInfo.getGraphHeight().intValue()),
                        new PdfMargins(0, 0, 0, 0));
                // 将文本布局设置为一页（适应页面大小）
                PdfTextLayout layout = new PdfTextLayout();
                layout.setLayout(PdfLayoutType.One_Page);
                PdfTemplate template = originPdf.getPages().get(i).createTemplate();
                template.draw(newPage, new Point2D.Float(0, 0),layout);
            }
            newPdf.saveToFile(filePath+"/"+graphInfo.getGraphName() + ".pdf", FileFormat.PDF);
            originPdf.close();
            newPdf.close();
            // 保存pdf的相对路径
            files.add(filePath+"/"+graphInfo.getGraphName() + ".pdf");
            tempFilePaths.add(filePath+"/"+graphInfo.getGraphName() + ".pdf");
        }

        String outPutName = "导出工程图纸.pdf";
        //合并数据
//        mergePdfFiles(files, filePath + "/" + outPutName);
        pdfFiles.add(filePath + "/" + outPutName);

        // zip压缩包名称
        try {
            // http响应信
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(outPutName, "UTF-8"));
            FileInputStream fileInputStream = new FileInputStream(filePath + "/" + outPutName);

            ServletOutputStream outputStream = response.getOutputStream();
            byte[] bytes = new byte[2048];
            int len = 0;
            while ((len = fileInputStream.read(bytes)) > 0) {
                outputStream.write(bytes, 0, len);
            }
            outputStream.flush();
            fileInputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 导出完成后，清除相对路径下的临时pdf文件
//        clearTempFiles(tempFilePaths);
    }

    @Override
    public void svgToPDF(String filePath) {
        PdfDocument newPdf = new PdfDocument();
        PdfDocument originPdf = new PdfDocument();
        originPdf.loadFromSvg(filePath+".svg");
        for (int i = 0; i < originPdf.getPages().getCount(); i++) {
            int GRAPH_WIDTH = 2245; // 图纸宽度
            int GRAPH_HEIGHT = 1587; // 图纸高度
            // 设置页面大小
            PdfPageBase newPage = newPdf.getPages().add(new Dimension(GRAPH_WIDTH, GRAPH_HEIGHT),
                    new PdfMargins(0, 0, 0, 0));
            // 将文本布局设置为一页（适应页面大小）
            PdfTextLayout layout = new PdfTextLayout();
            layout.setLayout(PdfLayoutType.One_Page);
            PdfTemplate template = originPdf.getPages().get(i).createTemplate();
            template.draw(newPage, new Point2D.Float(0, 0), layout);
        }
        originPdf.saveToFile( filePath+".pdf", FileFormat.PDF);
        originPdf.close();
        newPdf.close();
    }

    /**
     * 根据svg文字特殊处理
     * @param svgXml
     * @return
     */
    @Override
    public String getFontSvg(String svgXml,int flag) {
        // 文本标注预处理
        svgXml = SvgFontUtil.replaceTextNote(svgXml,flag);

        if(!(StringUtils.contains(svgXml,"<switch") && StringUtils.contains(svgXml,"<foreignObject"))){
            return svgXml;
        }
        // 1.获取数据集合
        Map<String, SvgFontElementModel> svgFontElement = SvgFontUtil.getSvgFontElement(svgXml);
//         2.替换文本数据
        return SvgFontUtil.replaceSVGXml(svgXml,svgFontElement,flag);
//        return svgXml;
    }

    @Override
    public void pdfMark(String instanceId) {

    }

    /**
     * 上传svg文件到本地
     *
     * @param svgStr   svg全数据
     * @param filePath 文件路径：cloudDream/uploadPath/svg
     * @param fileName 文件名称：id.svg
     * @return
     */
    public void uploadSvg(String svgStr,String filePath,String fileName) {
        File tempFile = new File(filePath);
        if (!tempFile.exists()) {
            tempFile.mkdirs();
        }
        // 删除旧文件
        File file = new File(filePath+"/"+fileName);
        if (file.exists()) {
            file.delete();
        }

        try {
            FileOutputStream outputStream = new FileOutputStream(filePath+"/"+fileName);
            OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
            writer.write(svgStr);
            writer.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * 合并pdf文件
     * @param files 要合并文件数组(绝对路径如{ "e:\\1.pdf", "e:\\2.pdf" ,
     * "e:\\3.pdf"}),合并的顺序按照数组中的先后顺序，如2.pdf合并在1.pdf后。
     * @param newfile 合并后新产生的文件绝对路径，如 e:\\temp\\tempNew.pdf,
     * @return boolean 合并成功返回true；否则，返回false
     *
     */
//    public static boolean mergePdfFiles(List<String> files, String newfile) {
//        boolean retValue = false;
//        Document document = null;
//        try {
//            PdfReader pdfReader = new PdfReader(files.get(0));
//            document = new Document(pdfReader.getPageSize(1));
//            FileOutputStream outputStream = new FileOutputStream(newfile);
//            PdfCopy copy = new PdfCopy(document, outputStream);
//            document.open();
//            for (int i = 0; i < files.size(); i++) {
//                PdfReader reader = new PdfReader(files.get(i));
//                int n = reader.getNumberOfPages();
//                for (int j = 1; j <= n; j++) {
//                    document.newPage();
//                    PdfImportedPage page = copy.getImportedPage(reader, j);
//                    copy.addPage(page);
//                }
//                reader.close();
//            }
//            retValue = true;
//
//            // 关流
//            copy.close();
//            outputStream.close();
//            document.close();
//            pdfReader.close();
//        } catch (Exception e) {
//            System.out.println(e);
//        } finally {
//            System.out.println("执行结束");
//        }
//        return retValue;
//    }

    // 清除临时文件pdf
    private void clearTempFiles(List<String> files) {
        for (String filePath : files) {
            Path path = Paths.get(filePath);
            try {
                Files.delete(path);
                log.info("临时文件被清除：" + path);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
